如果您的应用侧主要使用Java语言,且数据库连接创建频繁(例如短连接场景)或连接数量较大(大于MySQL数据库的连接数限制),您可以使用Java连接池Druid连接数据库,降低连接建立频率以减少数据库主线程的开销。
前提条件
应用服务器已安装Java环境且JDK版本在1.8及以上。
已将服务器IP地址添加至RDS实例白名单中,详情请参见设置IP白名单。
说明若您的应用程序部署在阿里云ECS服务器上,且ECS与RDS已实现内网互通(ECS与RDS实例的地域、VPC均相同),则无需设置IP白名单。
准备工作
本文以Maven项目为例,介绍使用Druid连接池连接数据库前的准备工作。
Maven是一个Java项目管理工具,其为开发者提供了一套标准化的Java项目构建流程与依赖管理机制。使用Maven创建的Java项目带有标准化的目录结构,其中pom.xml
为项目描述文件,src/main/java
目录存放项目的Java源代码,src/main/resources
目录存放项目资源文件。
安装Druid:您需要在
pom.xml
文件的dependencies
中添加以下依赖项安装Druid,Druid连接池版本建议选择1.2.13及以上。<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.19</version> </dependency>
通过
druid-spring-boot-starter
使用连接池Druid时,为了简化依赖关系,便于后续Druid版本的更新维护,您需要在pom.xml
文件的dependencies
中先排除其依赖的Druid组件,再显式依赖Druid组件,如下所示。<dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.19</version> <exclusions> <exclusion> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.19</version> </dependency>
使用Druid连接数据库
配置连接池参数:您需要在项目的
src/main/resources
目录中新建druid.properties
文件,并在文件中添加以下内容为连接池配置相关参数,参数说明详情请参见Druid连接池常见参数配置。说明RDS MySQL数据库连接地址和端口的获取方法,请参见查看和管理实例连接地址和端口。
# 驱动类名,无需替换 driverClassName=com.mysql.jdbc.Driver # url、username、password、database需要替换为业务实际的内容 url=jdbc:mysql://rm-bp**************.mysql.rds.aliyuncs.com:3306/database username=**** password=**** # 初始化时创建的连接数 initialSize=20 # 最小空闲连接数 minIdle=20 # 连接池最大连接数 maxActive=100 # 一条物理连接的存活时间 phyTimeoutMillis=3600000 # 获取连接最大等待时间,如果连接池中没有可用连接且已达到最大连接数,则应用获取连接的请求将被阻塞,最多等待maxWait(毫秒),建议保持不变 maxWait=5000 # 连接超时时间,表示数据库驱动和数据库服务器之间建立TCP连接的超时时间,单位毫秒 connectTimeout=20000 # Socket超时时间,表示通过TCP连接发送数据(执行的sql)后,等待响应的超时时间,单位毫秒 socketTimeout=60000 # 连接验证配置项,建议保持不变 testWhileIdle=true testOnBorrow=false testOnReturn=false # PreparedStatement缓存配置项,此处配置为true表示打开缓存,建议保持不变 poolPreparedStatements=true maxPoolPreparedStatementPerConnectionSize=100
使用连接池访问数据库:您需要在
src/main/java
目录存放的源代码文件中导入相关依赖,构建DruidPoolDemo
类,通过连接池Druid获取JDBC的连接信息并访问MySQL数据库。// 导入相关依赖 package com.aliyun.rdsfinops.collector.impl; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.InputStream; import java.sql.*; import java.util.Properties; public class DruidPoolDemo { private static DataSource dataSource = null; String tableName = "sql_table_test"; // 加载参数 static { Properties properties = new Properties(); // 获取连接池配置 InputStream inputStream = DruidPoolDemo.class.getClassLoader().getResourceAsStream("druid.properties"); try { properties.load(inputStream); // 初始化连接池 dataSource = DruidDataSourceFactory.createDataSource(properties); } catch (Exception e) { e.printStackTrace(); } } /* 后续数据库操作(见后文) 创建表: public void createTable() 插入数据:public void insertData() 查询数据:public void selectData() 删除数据:public void deleteData() */ }
连接池常见参数配置
在使用Druid连接数据库时,建议您根据下述内容为连接池设置合适的参数,使数据库的运行更稳定高效。
为了最大程度地避免潜在的风险和不确定性,在将新的参数值用于生产环境前,建议您至少进行一轮完整的功能测试和性能测试,以确保系统稳定性和可靠性。
推荐配置的参数
推荐您在使用Druid连接池时设置以下参数,降低数据库运行风险。
参数名 | 含义 | 默认值 | 推荐值 | 说明 |
initialSize | 连接池初始化时创建的连接数。 | 0 | 20~80 |
|
minIdle | 最小空闲连接数。 | 0 | 20~80 |
|
maxActive | 连接池最大连接数。 | 8 | 100 |
|
phyTimeoutMillis | 一条物理连接的存活时间(毫秒)。 | -1 | 3600000~28800000 |
|
maxWait | 获取连接时的最大等待时间(毫秒)。 | -1 | 5000 |
|
connectTimeout | 连接超时的时间(毫秒)。 | 10000 | 3000 |
|
socketTimeout | socket的超时时间(毫秒)。 | 10000 | 10000~60000 |
|
testWhileIdle | 是否开启空闲连接的检测。 | false | true | 建议设置为 |
可选择配置的参数
使用Druid连接池时,您可以选择性地配置以下参数,提升数据库性能。
参数名 | 含义 | 默认值 | 推荐值 | 说明 |
poolPreparedStatements | 是否缓存PreparedStatement对象。 | true | true |
|
maxPoolPreparedStatementPerConnectionSize | 每个连接缓存PreparedStatement对象的最大数量。 | 10 | 100 |
|
保持默认配置的参数
对于以下常见的连接池参数,您可以选择直接使用默认配置或根据自身需求调整参数。
参数名 | 含义 | 默认值 | 推荐值 | 说明 |
failFast | 用于控制在获取连接出现错误时的行为。 | false | false |
|
timeBetweenEvictionRunsMillis | 检测空闲连接的时间间隔(毫秒)。 | 60000 | 60000 |
|
后续数据库操作
您可以在DruidPoolDemo
类中添加自定义函数,满足对数据库操作的需求,本文以创建数据表、插入数据、查询数据、删除数据为例。
创建表
String tableName = "sql_table_test";
public void createTable() throws SQLException {
// 创建表
try (Connection connection = dataSource.getConnection()) {
try (Statement statement = connection.createStatement()) {
String sql = "create table if not exists " + tableName + "(id VARCHAR(255), name VARCHAR(255), PRIMARY KEY (id))";
int ret = statement.executeUpdate(sql);
System.out.println(ret);
}
}
}
插入数据
String tableName = "sql_table_test";
public void insertData(){
// 插入数据
try (Connection connection = dataSource.getConnection()) {
String sql = "insert into " + tableName + "(id,name) values(?,?)";
try (PreparedStatement ps = connection.prepareStatement(sql)) {
ps.setString(1, "aa");
ps.setString(2, "bb");
int ret = ps.executeUpdate();
System.out.println(ret);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
查询数据
String tableName = "sql_table_test";
public void selectData() throws SQLException {
// 查询数据
try (Connection connection = dataSource.getConnection()) {
String sql = "select * from " + tableName + " where id=?";
try (PreparedStatement ps = connection.prepareStatement(sql)) {
ps.setString(1, "aa");
ResultSet rs = ps.executeQuery();
while (rs.next()) {
String id = rs.getString(1);
String name = rs.getString(2);
System.out.println("id=" + id);
System.out.println("name=" + name);
}
}
}
}
删除数据
String tableName = "sql_table_test";
public void deleteData(){
// 删除数据
try (Connection connection = dataSource.getConnection()) {
String sql = "delete from " + tableName + " where id=?";
try (PreparedStatement ps = connection.prepareStatement(sql)) {
ps.setString(1, "aa");
ps.executeUpdate();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
相关文档
Python连接池:使用Python连接池DBUtils连接数据库
RDS MySQL数据库代理中的连接池功能:RDS MySQL设置连接池